package com.leyantech.ecp.agenx.translator.converter.input;

import static com.leyantech.ecp.agenx.common.utils.SplitterUtils.COLON_SPLITTER;

import com.leyantech.ai.DialogDirection;
import com.leyantech.ai.DialogueQuestion;
import com.leyantech.ai.Extension;
import com.leyantech.ai.Platform;
import com.leyantech.ai.ServiceMode;
import com.leyantech.ai.ServiceType;
import com.leyantech.ecp.agenx.common.converter.input.DialogueQuestionConverter;
import com.leyantech.ecp.agenx.common.redis.RedissonOperation;
import com.leyantech.ecp.agenx.common.service.StoreConfigService;
import com.leyantech.ecp.agenx.common.service.StoreHomeService;
import com.leyantech.ecp.agenx.common.utils.CacheUtils;
import com.leyantech.ecp.agenx.common.utils.UrlUtils;
import com.leyantech.ecp.agenx.session.client.Assistant;
import com.leyantech.ecp.agenx.session.client.SessionClient;
import com.leyantech.ecp.agenx.translator.config.EnumPddMsgType;
import com.leyantech.storehome.ProductVersionInfo;

import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.inject.Inject;
import io.vertx.core.json.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RObject;

import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Supplier;

/**
 * @author eahau, {@literal <eahau@foxmail.com>}
 * @date 2022-11-01.
 */
@Slf4j
public class PinDuoDuoQuestionConverter implements DialogueQuestionConverter {

  private final SessionClient sessionClient;

  private final StoreConfigService storeConfigService;

  private final StoreHomeService storeHomeService;

  final Supplier<LoadingCache<String, Boolean>> storeReplyCache = CacheUtils
      .buildCache("StoreReply", this::canReply);

  @Inject
  public PinDuoDuoQuestionConverter(SessionClient sessionClient,
      StoreConfigService storeConfigService,
      StoreHomeService storeHomeService) {
    this.sessionClient = sessionClient;
    this.storeConfigService = storeConfigService;
    this.storeHomeService = storeHomeService;
  }

  @Override
  public DialogueQuestion apply(JsonObject jsonObject) {

    JsonObject message = jsonObject.getJsonObject("message");

    int type = message.getInteger("type");
    EnumPddMsgType pddMsgType = EnumPddMsgType.getEnumPddMsgType(type);
    if (pddMsgType == null) {
      log.warn("Unsupported message type {}", type);
      return DialogueQuestion.getDefaultInstance();
    }

    String userNickName = message.getString("nickname", "");

    JsonObject from = message.getJsonObject("from");
    String fromRole = from.getString("role", "");

    String uid = "";
    boolean belongPlatformBotMsg = false;
    DialogDirection dialogDirection;
    switch (fromRole) {
      case "user":
        dialogDirection = DialogDirection.INCOME;
        uid = from.getString("uid");
        break;
      case "system":
        dialogDirection = DialogDirection.OUTGOING;
        belongPlatformBotMsg = true;
        break;
      default:
        dialogDirection = DialogDirection.OUTGOING;
        belongPlatformBotMsg = message.getBoolean("show_auto", false);
        uid = message.getJsonObject("to").getString("uid");
        break;
    }

    String content;

    String spuId = "";
    String orderId = "";

    switch (pddMsgType) {
      case IMAGE:
      case IMAGE_2:
        content = "[图片]";
        break;
      case VIDEO:
        content = "[视频]";
        break;
      case MSG_FROM_GOODS_INFO_PAGE:
        // 来自 商品详情页的买家消息
        content = genFromItemInfoPageMsg(message);
        spuId = getSpuIdFromGoodsInfo(message);
        break;
      case PDD_SYSTEM_MARKETING:
        // pdd 官方营销.
        JsonObject data = message.getJsonObject("data");
        content = data.getString("notice");
        uid = data.getString("uid");
        break;
      case BUYER_APPLY_POST_SALES_SERVICE:
        content = message.getString("content");
        if ("[咨询商品规格]".equals(content)) {
          spuId = getSpuFromItemCard(message);
          if (StringUtils.isNotBlank(spuId)) {
            content = "https://mobile.yangkeduo.com/goods.html?goods_id=" + spuId;
          }
        }
        break;
      default: {
        // 一般普通消息，都可以从 content 中取
        content = message.getString("content");
        if (content.startsWith("订单编号:") || "订单卡片".equals(content)) {
          final JsonObject info = message.getJsonObject("info");
          if (info != null) {
            orderId = info.getString("orderSequenceNo", "");
          } else {
            final List<String> orderIdList = COLON_SPLITTER.splitToList(content);
            // 订单编号:{orderId}
            if (CollectionUtils.size(orderIdList) == 2) {
              orderId = orderIdList.get(1);
            }
          }
        }
        spuId = genSpuFromItemLink(content);
      }
        break;
    }

    DialogueQuestion.Builder builder = DialogueQuestion.newBuilder();

    final String storeId = jsonObject.getString("sid");
    final String aid = jsonObject.getString("aid");

    // 推荐商品只是发个动作，由客户端选择的商品，所以下发时不知道商品 id。客户端会再次上报，触发催下单，所以需要忽略掉
    // todo 暂时帮 oppo 做过滤
    if (dialogDirection == DialogDirection.OUTGOING) {
      if (StringUtils.isNotBlank(spuId)) {
        final String key = String.join(".", aid, uid);
        final boolean exists = RedissonOperation.ITEM_CARD
            .executor(key)
            .get(RObject::isExists, "isExists");
        if (exists) {
          return DialogueQuestion.getDefaultInstance();
        }
      }
    }

    final String messageId = UUID.randomUUID().toString();

    final Optional<Assistant> onlineAssistant = sessionClient.getOnlineAssistant(storeId, aid);

    final String assistantNick = onlineAssistant.map(Assistant::getAssistantName)
        .orElse(aid);

    final String serviceModeString = jsonObject
        .getString("service_mode", ServiceMode.NORMAL.name());
    final ServiceMode serviceMode = ServiceMode.valueOf(serviceModeString.toUpperCase());

    final Long timestamp = jsonObject.getLong("ts");

    builder.setRetailStoreId(storeId)
        .setAssistantId(aid)
        .setAssistantNick(assistantNick)
        .setUserId(uid)
        .setSessionId(String.join(".", storeId, uid))
        .setMessageId(messageId)
        .setTimestamp(timestamp != null ? timestamp : System.currentTimeMillis())
        .setUuid(messageId)
        .setServiceMode(serviceMode)
        .setUserDomain("ecp-pdd")
        .setApp("chat-pdd")
        .setQuery(content)
        .setPlatform(Platform.ECP_PDD)
        .setUserNickAvatar(userNickName)
        .setDirection(dialogDirection)
        .setAssistantDomain("ecp-agenx");

    switch (dialogDirection) {
      case INCOME:
        // 买家问题
        builder.setServiceType(ServiceType.QUESTION);
        break;
      case OUTGOING:
        // 属于卖家回复
        builder.setServiceType(belongPlatformBotMsg
            ? ServiceType.SERVICE_TYPE_AUTO_REPLY
            : ServiceType.SERVICE_TYPE_OUTGOING);
        break;
    }

    if (pddMsgType == EnumPddMsgType.ASSISTANT_TRANSFER_MSG) {
      builder.setServiceType(ServiceType.TRANSFER_QUESTION);
    }

    // 如果是 直接明确不能回复的，则直接 DISABLED
    boolean canReply = Boolean.TRUE.equals(storeReplyCache.get().get(storeId));
    if (!canReply) {
      builder.setServiceMode(ServiceMode.DISABLED);
    } else if (pddMsgType == EnumPddMsgType.MSG_FROM_GOODS_INFO_PAGE
        || pddMsgType == EnumPddMsgType.PDD_SYSTEM_MARKETING) {
      // 买家来自详情页的消息，dialogue 不需要做处理
      // pdd- 官方营销也不会做处理
      builder.setServiceMode(ServiceMode.DISABLED);
    }

    final Extension.Builder extensionBuilder = Extension.newBuilder()
        .setOrderId(orderId)
        .setItemId(spuId);

    onlineAssistant.map(Assistant::getClientUuid).ifPresent(extensionBuilder::setDeviceNo);

    if (onlineAssistant.map(Assistant::getServiceMode)
        .filter(ServiceMode.MIX.name()::equalsIgnoreCase)
        .isPresent()) {
      builder.setServiceMode(ServiceMode.MIX);
      onlineAssistant.map(Assistant::getFunctionList)
          .ifPresent(extensionBuilder::addAllServiceModeFunc);
    }
    builder.setExtension(extensionBuilder);

    return builder.build();
  }

  private static String getSpuFromItemCard(JsonObject message) {
    return Optional.ofNullable(message.getJsonObject("info"))
        .map(jsonObject -> jsonObject.getJsonObject("data"))
        .map(jsonObject -> jsonObject.getString("goods_id"))
        .orElse("");
  }

  private static String genFromItemInfoPageMsg(JsonObject message) {
    return Optional.ofNullable(message.getJsonObject("info"))
        .map(info -> info.getJsonObject("goods_info"))
        .map(goodsInfo -> goodsInfo.getString("mall_link_url"))
        .orElse("");
  }

  private static String getSpuIdFromGoodsInfo(JsonObject message) {
    return Optional.ofNullable(message.getJsonObject("info"))
        .map(info -> info.getJsonObject("goods_info"))
        .map(goodsInfo -> goodsInfo.getString("goods_id"))
        .orElse("");
  }

  private static String genSpuFromItemLink(String content) {
    if (StringUtils.contains(content, "mobile.yangkeduo.com/goods.html?goods_id")) {
      return UrlUtils.extractUrl(content)
          .map(httpUrl -> httpUrl.queryParameter("goods_id"))
          .orElse("");
    }
    return "";
  }

  private boolean canReply(String sid) {
    return storeHomeService.getProductVersionInfo(sid)
        .map(ProductVersionInfo::getIsReply)
        .orElse(true);
  }

}
